package cn.com.cetccst.location.peroid;

import static cn.com.cetccst.location.LocationService.sKVStore;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.text.format.DateUtils;
import android.util.Log;

import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;

import java.util.concurrent.TimeUnit;

//周期定位
//周期定位更像是业务数据，这里单独封装在一起，后面移动到其他合适位置。
public class PeroidLocateHelper {
    public static final String TAG = "PeroidLocateHelper";

    public static final String KEY_ADMIN_PEROID_LOCATE_STATE_VALUE = "admin_peroid_locate_state_value";
    public static final String KEY_ADMIN_PEROID_LOCATE_INTERVAL_VALUE = "admin_peroid_locate_interval_value";
    public static final String KEY_ADMIN_LAST_REPORT_LOCATION_TIME_VALUE = "admin_last_report_location_time_value";

    //定时上报位置以小时为单位
    private static final long POST_LOCATION_UNIT = DateUtils.MINUTE_IN_MILLIS;//2 * DateUtils.MINUTE_IN_MILLIS;

    private Context mContext;
    private boolean mPeroidLocateState;
    private int mPeroidLocateInterval;

    //上一次周期执行时间
    private long mLastReportTime;

    private static final String WORKER_ID = "peroid_locate_worker";

    public PeroidLocateHelper(Context context) {
        this.mContext = context;
        loadCfgAndStart();
    }

    public void loadCfgAndStart() {
        if (sKVStore == null) {
            Log.e(TAG,"init kv store first");
            return;
        }
        mPeroidLocateState = sKVStore.decodeBool(KEY_ADMIN_PEROID_LOCATE_STATE_VALUE, true);
        mPeroidLocateInterval = sKVStore.decodeInt(KEY_ADMIN_PEROID_LOCATE_INTERVAL_VALUE, 15);
        mLastReportTime = sKVStore.decodeLong(KEY_ADMIN_LAST_REPORT_LOCATION_TIME_VALUE);
//        start();
        startWorker();
    }

    //AlarmManager的重复时间可以小于15min，但是对于周期定位来说，最小单位是小时，使用WorkManager就可以满足要求，既然已经实现了就先保留着，以备不时之需
    public void start() {
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(mContext, PeroidLocateReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        alarmManager.cancel(pendingIntent);

        if (!mPeroidLocateState || mPeroidLocateInterval <= 0) {
            Log.e(TAG, "admin not enabled period location state: " + mPeroidLocateState + ", interval :" + mPeroidLocateInterval);
            return;
        }
        long currentTime = System.currentTimeMillis();
        long nextReportTime = Math.max(mLastReportTime + mPeroidLocateInterval * POST_LOCATION_UNIT, currentTime);

        Log.i(TAG, "Schedule location status posting in " + (nextReportTime)
                + ", and the following interval hours is " + mPeroidLocateInterval);
        alarmManager.setRepeating(AlarmManager.RTC,
                nextReportTime + 5 * 1000,
                mPeroidLocateInterval * POST_LOCATION_UNIT, pendingIntent);
    }

    //周期定位需求设计间隔是以小时为单位，WorkManager的最小间隔为15min，所以可以满足要求
    public void startWorker() {
        if (!mPeroidLocateState || mPeroidLocateInterval <= 0) {
            Log.e(TAG, "admin not enabled period location state: " + mPeroidLocateState + ", interval :" + mPeroidLocateInterval);
            WorkManager.getInstance(mContext).cancelUniqueWork(WORKER_ID);
            return;
        }

        long delay = 5 * 1000;
        long now = System.currentTimeMillis();
        //已经过了上报时间，手动重新计时
        if ((mLastReportTime + mPeroidLocateInterval * POST_LOCATION_UNIT) < now) {
            Log.i(TAG, "need restart the worker " + delay);
            WorkManager.getInstance(mContext).cancelUniqueWork(WORKER_ID);
        }

        Log.i(TAG, "Schedule location status posting in " + delay
                + ", and the following interval hours is " + mPeroidLocateInterval);
        PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(PeroidLocateWorker.class,
                mPeroidLocateInterval, TimeUnit.MINUTES)// 最小15分钟
                .setInitialDelay(delay, TimeUnit.MILLISECONDS)
                .build();
        //ExistingPeriodicWorkPolicy.UPDATE 可以保证执行周期内重启，下次执行时间继续执行。
        WorkManager.getInstance(mContext).enqueueUniquePeriodicWork(WORKER_ID, ExistingPeriodicWorkPolicy.UPDATE, periodicWork);
    }

    public boolean isPeroidLocateEnabled() {
        return mPeroidLocateState;
    }

    public void setPeroidLocateEnabled(boolean peroidLocateState) {
        mPeroidLocateState = peroidLocateState;
    }

    public int getPeroidLocateInterval() {
        return mPeroidLocateInterval;
    }

    public void setPeroidLocateInterval(int peroidLocateInterval) {
        mPeroidLocateInterval = peroidLocateInterval;
    }

    public long getLastReportTime() {
        return mLastReportTime;
    }

    public void setLastReportTime(long lastReportTime) {
        sKVStore.encode(KEY_ADMIN_LAST_REPORT_LOCATION_TIME_VALUE, lastReportTime);
        mLastReportTime = lastReportTime;
    }
}
